package xj.graph2d.graph;

import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.List;
import java.util.ArrayList;

public class Cluster<NodeType extends GraphNode> {

  public Cluster() {
  }

  public int getHeight() {
    return height;
  }

  public void setHeight(int h) {
    height = h;
  }

  public int size() {
    return nodes.size();
  }

  public boolean contains(NodeType n) { 
    return nodes.contains(n);
  }

  public Set<NodeType> getNodeSet() { 
    return nodes; 
  }

  public NodeType getRoot() {
    return root;
  }

  public void setRoot(NodeType root) {
    this.root = root;
  }

  public Iterator<NodeType> iterator() {
    return nodes.iterator();
  }

  public void add(NodeType node) {
    if (node != null) { 
      nodes.add(node);
    }
  }

  public void remove(NodeType node) {
    if (node != null) { 
      nodes.remove(node);
    }
  }

  public void move(float dx, float dy) {
    for (Iterator<NodeType> iter = nodes.iterator(); iter.hasNext();) {
      NodeType node = iter.next();
      if (node != null) {
	node.move(dx, dy);
      }
    }
  }

  public Rectangle2D getBounds() {
    Rectangle2D rect = null;
    Iterator<NodeType> niter = nodes.iterator();
    while (niter.hasNext()) {
      NodeType node = niter.next();
      if (node != null) {
	Point2D p = node.getULCorner();
	Dimension2D d = node.getSize();
	Rectangle2D r = new Rectangle2D.Float((float) p.getX(), (float) p.getY(), 
					      (float) d.getWidth(), (float) d.getHeight());
	if (rect == null) {
	  rect = r;
	} else {
	  Rectangle2D.union(rect, r, rect);
	}
      }
    }
    if (rect != null) {
      return rect;
    } else {
      return new Rectangle2D.Float(0, 0, 0, 0);
    }
  }

  public int getMaxBreadth() { 
    if (height > 0 && 
	nodes.size() > 0) {
      int[] b = new int[height];
      Iterator<NodeType> iter = nodes.iterator();
      while (iter.hasNext()) {
	NodeType node = iter.next();
	int h = node.getHeight();
	if (h >= height) { 
	  h = height - 1;
	}
	b[h]++;
      }
      int max = b[0];
      for (int i = 1; i < height; i++) { 
	if (b[i] > max) {
	  max = b[i];
	}
      }
      return max; 
    }
    return 0;
  }

  @Override
  public String toString() {
    return ("Cluster: size=" + size() + " height=" + getHeight());
  }

  public String nodeNames() {
    StringBuilder result = new StringBuilder();
    Iterator<NodeType> niter = nodes.iterator();
    while (niter.hasNext()) {
      NodeType node = niter.next();
      if (node != null) {
	result.append(node.toString()).append(" ");
      }
    }
    return result.toString();
  }

  protected NodeType root;

  protected Set<NodeType> nodes = new HashSet<NodeType>();

  protected int height = 0;

}
